package work.thread_eg.concurrent.lock;


import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * ReentrantLock 可重入锁 (synchronized也是可重入锁)
 * ReentrantLock可以替代 synchronized
 * lock需要手动释放锁 synchronized是自动解锁  unlock要写在try finally里面
 *
 * tryLock() 可以决定要不要wait
 * lockInterruptibly() 可中断 可以对线程的interrupt()方法做出响应 中断等待获取锁的线程
 *
 */
public class ReentrantLockTest01 {

    // 同一个ReentrantLock代表同一个锁
    Lock lock = new ReentrantLock();

    void m1() {
        try {
            lock.lock();
            for(int i= 0 ; i<10; i++) {
                TimeUnit.SECONDS.sleep(1);
                System.out.println(i);
            }
        }catch (InterruptedException ex) {
            ex.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    void m2() {
        boolean locked = false;
        try {
            // 尝试申请在5秒内拿到锁
            // 返回true表示拿到锁 就不需要再使用lock()方法了
            // 返回false 拿不到锁程序会继续往下执行
            // 直接使用lock就会阻塞在那里了
            // tryLock() 添加参数 时间段内 代码会阻塞在这里 会一直尝试拿锁
            // tryLock() 不加参数 会立即返回锁的状态
            locked = lock.tryLock(5,TimeUnit.SECONDS);
//            locked = lock.tryLock();
            System.out.println("m2 ..." + locked);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("m2 ... finally");
            if(locked) lock.unlock();
        }
    }

    public static void main(String[] args) {
        ReentrantLockTest01 t1 = new ReentrantLockTest01();
        Thread thread1 = new Thread(t1::m1);
        thread1.start();
        try {
            TimeUnit.SECONDS.sleep(1);
        }catch (InterruptedException ex) {
            ex.printStackTrace();
        }
        Thread thread2 = new Thread(t1::m2);
        thread2.start();
    }
}
